﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static BaseHeightControl.BoxBody;

namespace BaseHeightControl
{
    /// <summary>
    /// 建筑物
    /// </summary>
    public partial class Building : ObservableObject
    {
        /// <summary>
        /// 名称
        /// </summary>
        [ObservableProperty]
        public string _Name;
        /// <summary>
        /// 描述
        /// </summary>
        [ObservableProperty]
        public string _Description;
        /// <summary>
        /// 箱体列表
        /// </summary>
        [ObservableProperty]
        public List<BoxBody> _BoxBodies;
        /// <summary>
        /// 楼层列表
        /// </summary>
        [ObservableProperty]
        public List<Floor> _Floors;

        public Building()
        {
            BoxBodies = new List<BoxBody>();
            Floors = new List<Floor>();
        }
        public delegate void ReBackDatas_InBuilding(string Msg = "");
        public event ReBackDatas_InBuilding? ReBackData_InBuilding;


        #region 初始化需要配置的委托
        public void AddBox(BoxBody box)
        {
            BoxBodies.Add(box);
            box.ReBackData_InBoxBody += Box_ReBackDatas;
        }

        private void Box_ReBackDatas(string Msg)
        {
            switch (Msg)
            {
                
                case "↓请重新计算楼层":
                    {
                        Boxies_CurrentNameOfFloor_In_Building();//计算电梯在楼层高度中对应的楼层名称
                        Boxies_CurrentStatus_In_Building();
                    }
                    break;
                case "↑请重新计算楼层":
                    {
                        Boxies_CurrentNameOfFloor_In_Building();//计算电梯在楼层高度中对应的楼层名称
                        Boxies_CurrentStatus_In_Building();
                    }
                    break;
                default:
                    {
                        if (Msg.Contains("到达目标楼层"))
                        {
                            Boxies_CurrentNameOfFloor_In_Building();//计算电梯在楼层高度中对应的楼层名称
                            //这里要清除
                            ClearBoxes(Msg);
                        }
                        if (Msg.Contains("楼层控制面板打开"))
                        {
                            //某楼层的控制面板打开
                            ReBackData_InBuilding?.Invoke(Msg);
                        }
                        if (Msg.Contains("在楼层控制面板中点击了"))
                        {
                            //某楼层的控制面板关闭
                            ReBackData_InBuilding?.Invoke(Msg);
                        }
                    }
                    break;
            }
        }

        private void ClearBoxes(string msg)
        {
            List<int> list_Up_Button = new List<int>();//按下的按钮是向上的
            List<int> list_Down_Button = new List<int>();//按下的按钮是向下的

            //2025年10月23日13:38:54 顺便把目标高度也计算出来
            List<decimal> list_TargetHeight_Up = new List<decimal>();
            List<decimal> list_TargetHeight_Down = new List<decimal>();



            TargetHeight_On_Earth(ref list_Up_Button, ref list_Down_Button, ref list_TargetHeight_Up, ref list_TargetHeight_Down);//各楼层的目标坐标计算

            var list = msg.Split(',');
            string diantiName = list[0];

            if (list_TargetHeight_Up.Count == 0 && list_TargetHeight_Down.Count == 0)
            {
                //for (int i = 0; i < BoxBodies.Count; i++)
                //{
                //    BoxBodies[i].CurrentStatus_In_Building = "-";
                //}
            }
            else
            {
                for (int i = 0; i < BoxBodies.Count; i++)
                {
                    if (BoxBodies[i].Name == diantiName)
                    {
                        //找到这个电梯，并确定这个电梯在几楼，什么方向运行。
                        var louceng = BoxBodies[i].CurrentNameOfFloor_In_Building;
                        var fangxiang = BoxBodies[i].CurrentStatus_In_Building;
                        //把楼层这个按钮处理掉
                        for (int j = 0; j < Floors.Count; j++)
                        { 
                            if ($"{Floors[j].FloorNumber}楼" == louceng)
                            {
                                if (fangxiang == "↑")
                                    Floors[j].IsUpButtonOn =  false; 
                                if (fangxiang == "↓")
                                    Floors[j].IsDownButtonOn = false; 

                                if (Floors[j].IsTopOrBottom == FloorLevel.Top || Floors[j].IsTopOrBottom == FloorLevel.Bottom)
                                {
                                    //如果是顶楼或底楼，清除按钮 2025年10月24日08:22:42
                                    Floors[j].IsUpButtonOn = false;
                                    Floors[j].IsDownButtonOn = false;
                                }

                                if (fangxiang == "-")
                                {
                                    Floors[j].IsUpButtonOn = false;
                                    Floors[j].IsDownButtonOn = false;
                                }


                                break;
                            }
                        }

                        break;
                    }
                }
                
            }

            AutoRun_Logic();
        }





        #endregion

        [RelayCommand]
        public void Button_Up(object parameter)
        {
            Console.WriteLine($"刚刚点击的按钮是 【{parameter}楼 向上】{DateTime.Now}");
            Set_FloorButton_On((int)parameter, "Up");
        }

        [RelayCommand]
        public void Button_Down(object parameter)
        {
            Console.WriteLine($"刚刚点击的按钮是 【{parameter}楼 向下】{DateTime.Now}");
            Set_FloorButton_On((int)parameter, "Down");
        }

        #region 内部算法

        /// <summary>
        /// 查询楼层内部数据，把对应的按钮触发状态设置为true
        /// </summary>
        /// <param name="floorNumber"></param>
        /// <param name="up_or_down"></param>
        private void Set_FloorButton_On(int floorNumber, string up_or_down)
        {
            foreach (var floor in Floors)
            {
                var t = floor.Set_IsUpButtonOn(floorNumber, up_or_down);
                if (t)
                {
                    //此处触发电梯运行的运算逻辑
                    AutoRun_Logic();
                }
            }
        }
        /// <summary>
        /// 电梯组自动运行逻辑运算
        /// </summary>
        private void AutoRun_Logic()
        {
            List<int> list_Up_Button = new List<int>();//按下的按钮是向上的
            List<int> list_Down_Button = new List<int>();//按下的按钮是向下的

            //2025年10月23日13:38:54 顺便把目标高度也计算出来
            List<decimal> list_TargetHeight_Up = new List<decimal>();
            List<decimal> list_TargetHeight_Down = new List<decimal>();

            

            TargetHeight_On_Earth(ref list_Up_Button, ref list_Down_Button, ref list_TargetHeight_Up, ref list_TargetHeight_Down);//各楼层的目标坐标计算

            Altitude();//各个楼层的海拔高度计算

            Boxies_CurrentNameOfFloor_In_Building();//计算电梯在楼层高度中对应的楼层名称

            Boxies_CurrentStatus_In_Building();//电梯运行趋势计算

            Make_RealBoxexLogic(list_TargetHeight_Up, list_TargetHeight_Down);//真正的电梯运行逻辑
            

        }
        /// <summary>
        /// 各楼层的目标坐标计算
        /// </summary>
        /// <param name="list_Up_Button"></param>
        /// <param name="list_Down_Button"></param>
        /// <param name="list_TargetHeight_Up"></param>
        /// <param name="list_TargetHeight_Down"></param>
        private void TargetHeight_On_Earth(ref List<int> list_Up_Button, ref List<int> list_Down_Button, ref List<decimal> list_TargetHeight_Up, ref List<decimal> list_TargetHeight_Down)
        {
            #region 先看看哪些楼层按按钮了。

            for (int i = 0; i < Floors.Count; i++)
            {
                if (Floors[i].IsUpButtonOn)
                {
                    list_Up_Button.Add(Floors[i].FloorNumber);
                    list_TargetHeight_Up.Add(Floors[i].Altitude);//顺便把目标高度也计算出来
                }
                else if (Floors[i].IsDownButtonOn)
                {
                    list_Down_Button.Add(Floors[i].FloorNumber);
                    list_TargetHeight_Down.Add(Floors[i].Altitude); //顺便把目标高度也计算出来
                }
            }
            #endregion
        }

        /// <summary>
        /// 各个楼层的海拔高度计算
        /// </summary>
        public void Altitude()
        {

            #region 计算一下各个楼层所在高度  OK，楼层所在高度计算完毕。先算建筑高度，不考虑地下，然后把地面层所在高度，从列表中减掉。OK 2025年10月23日10:01:12
            var OnFloor_Height = new List<double>();//存储各个楼层所在高度

            int findBaseFloor_Index = -1;//找到基层true，没找到false，找到之前是正数，找到之后是负数

            //先计算楼层位置，不考虑地下属性
            for (int i = 0; i < Floors.Count; i++)
            {
                if (Floors[i].IsBaseFloor)
                {
                    findBaseFloor_Index = i;
                }

                double total_Height = 0;
                for (int jishuanIndex = i; jishuanIndex < Floors.Count; jishuanIndex++)
                {
                    total_Height = total_Height + Floors[jishuanIndex].Height;
                }
                OnFloor_Height.Add(total_Height);
            }

            //然后根据基层索引，为基数，其他楼层减掉这个高度即可。
            double base_Height = OnFloor_Height[findBaseFloor_Index];
            if (findBaseFloor_Index != -1)
            {
                for (int i = 0; i < OnFloor_Height.Count; i++)
                {
                    OnFloor_Height[i] = OnFloor_Height[i] - base_Height;
                }
            }

            //把计算数据配置到楼层中
            for (int i = 0; i < Floors.Count; i++)
            {
                Floors[i].Altitude = (decimal)OnFloor_Height[i];
            }

            #endregion
        }
        /// <summary>
        /// 计算电梯在楼层高度中对应的楼层名称
        /// </summary>
        public void Boxies_CurrentNameOfFloor_In_Building()
        {
            try
            {
                for (int boxIndex = 0; boxIndex < BoxBodies.Count; boxIndex++)//循环所有电梯
                {
                    var currentHeight_FromSensor = BoxBodies[boxIndex].CurrentHeight_FromSensor;

                    for (int floorIndex = 0; floorIndex < Floors.Count; floorIndex++)//循环所有楼层
                    {
                        if (floorIndex == 0)
                        {
                            if (currentHeight_FromSensor >= (Floors[floorIndex].Altitude - BoxBodies[boxIndex].BaseSensorHeight))
                            {
                                BoxBodies[boxIndex].CurrentNameOfFloor_In_Building = $"{Floors[floorIndex].FloorNumber}楼";
                                break;
                            }
                        }
                        else if (currentHeight_FromSensor >= (Floors[floorIndex].Altitude - BoxBodies[boxIndex].BaseSensorHeight) &&
                            currentHeight_FromSensor < (Floors[floorIndex - 1].Altitude))
                        {
                            BoxBodies[boxIndex].CurrentNameOfFloor_In_Building = $"{Floors[floorIndex].FloorNumber}楼";
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        /// <summary>
        /// 电梯运行趋势计算
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void Boxies_CurrentStatus_In_Building()
        {
            #region 当前电梯都在干什么
            for (int i = 0; i < BoxBodies.Count; i++)
            {
                if (BoxBodies[i].CurrentHeight_FromSensor < BoxBodies[i].TargetHeight_FromControl)//当前高度小于目标高度
                {
                    //电梯向上运行
                    BoxBodies[i].CurrentStatus_In_Building = "↑";
                }
                else if (BoxBodies[i].CurrentHeight_FromSensor > BoxBodies[i].TargetHeight_FromControl)//当前高度大于目标高度
                {
                    //电梯向下运行
                    BoxBodies[i].CurrentStatus_In_Building = "↓";
                }
                else
                {
                    //这里需要增加一个验证，看看电梯是不是还行待执行的任务，如果有任务，就不能把其运行趋势设置为停止。2025年11月7日09:10:05
                    if (BoxBodies[i].ControlPanel_FloorNumbers.Count > 0)
                    {
                        //说明还有任务，不需要修改当前运行趋势
                    }
                    else
                    {
                        //说明没有任务，可以停止运行


                        //电梯停止运行
                        BoxBodies[i].CurrentStatus_In_Building = "-";
                    }

                }

            }
            #endregion
        }

        /// <summary>
        /// 运行逻辑
        /// </summary>
        /// <param name="list_TargetHeight_Up"></param>
        /// <param name="list_TargetHeight_Down"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void Make_RealBoxexLogic(List<decimal> list_TargetHeight_Up, List<decimal> list_TargetHeight_Down)
        {
            for (int boxIndex = 0; boxIndex < BoxBodies.Count; boxIndex++)
            {
                var box = BoxBodies[boxIndex];//当前这部电梯
                //让box在其内部进行运算
                box.LogicToDo(Floors);
            }

            #region 我想先屏蔽一下内容，让逻辑回归到电梯。让电梯内部自动计算，不要集中控制。2025年11月5日15:18:04


            /*
            for (int boxIndex = 0; boxIndex < BoxBodies.Count; boxIndex++)
            {
                var box = BoxBodies[boxIndex];//当前这部电梯
                switch (box.CurrentStatus_In_Building )
                {
                    case "↑":
                        {

                            //该电梯正在上行，这种情况下，只监测要上行的列表
                            for (int i = 0; i < list_TargetHeight_Up.Count; i++)
                            {
                                if (box.TargetHeight_FromControl == box.CurrentHeight_FromSensor)
                                {
                                    box.TargetHeight_FromControl = list_TargetHeight_Up[i];
                                }
                                if (box.TargetHeight_FromControl > list_TargetHeight_Up[i] &&box.CurrentHeight_FromSensor < list_TargetHeight_Up[i])
                                {
                                    box.TargetHeight_FromControl = list_TargetHeight_Up[i];
                                }
                            }
                        }
                        break;
                    case "↓":
                        {

                            //该电梯正在下行，这种情况下，只监测要下行的列表
                            for (int i = 0; i < list_TargetHeight_Down.Count; i++)
                            {
                                if (box.TargetHeight_FromControl == box.CurrentHeight_FromSensor)
                                {
                                    box.TargetHeight_FromControl = list_TargetHeight_Down[i];
                                }
                                else if (box.TargetHeight_FromControl < list_TargetHeight_Down[i] && box.CurrentHeight_FromSensor > list_TargetHeight_Down[i])
                                {
                                    box.TargetHeight_FromControl = list_TargetHeight_Down[i];
                                }
                            }
                        }
                        break;
                    case "-":
                        {
                            //该电梯停了，上下都得看看。找一个离它最近的。

                            decimal testTargetHeight_Up = box.TargetHeight_FromControl;//TODO:这块保证是错的，需要处理一下。2025年10月24日10:48:37
                            decimal testTargetHeight_Down = box.TargetHeight_FromControl;//这两个数据一会需要对比一下，哪个离它最近。

                            for (int i = 0; i < list_TargetHeight_Up.Count; i++)
                            {
                                if (box.TargetHeight_FromControl == box.CurrentHeight_FromSensor)
                                {
                                    testTargetHeight_Up = list_TargetHeight_Up[i];
                                }
                                else if (box.TargetHeight_FromControl > list_TargetHeight_Up[i] && box.CurrentHeight_FromSensor < list_TargetHeight_Up[i])
                                {
                                    testTargetHeight_Up = list_TargetHeight_Up[i];
                                }
                            }
                            for (int i = 0; i < list_TargetHeight_Down.Count; i++)
                            {
                                if (box.TargetHeight_FromControl == box.CurrentHeight_FromSensor)
                                {
                                    testTargetHeight_Down = list_TargetHeight_Down[i];
                                }
                                else if (box.TargetHeight_FromControl < list_TargetHeight_Down[i] && box.CurrentHeight_FromSensor > list_TargetHeight_Down[i])
                                {
                                    testTargetHeight_Down = list_TargetHeight_Down[i];
                                }
                            }

                            var t1 = testTargetHeight_Up - box.CurrentHeight_FromSensor;//上行接人距离
                            var t2 = box.CurrentHeight_FromSensor - testTargetHeight_Down;//下行接人距离
                            if (t1 > t2)
                            {
                                //下行接人更近
                                box.TargetHeight_FromControl = testTargetHeight_Down;
                                //box.CurrentStatus_In_Building = "↓";
                            }
                            else if(t1 < t2)
                            {
                                //上行接人更近
                                box.TargetHeight_FromControl = testTargetHeight_Up;
                                //box.CurrentStatus_In_Building = "↑";
                            }
                            else
                            {
                                //距离相同，优先下行
                                box.TargetHeight_FromControl = testTargetHeight_Up;
                                //box.CurrentStatus_In_Building = "↑";
                            }
                        }
                        break;
                    case "?":
                        { 
                        }
                        break;
                    default:
                        break;
                }
            }

            */

            #endregion
        }

        #endregion

    }
    /// <summary>
    /// 楼层（为建筑物提供基础的数据）
    /// </summary>
    public partial class Floor : ObservableObject
    {
        /// <summary>
        /// 楼层编号
        /// </summary>
        [ObservableProperty]
        public int _FloorNumber;
        /// <summary>
        /// 楼层高度
        /// </summary>
        [ObservableProperty]
        public double _Height;
        /// <summary>
        /// 海拔高度，相对地面。
        /// </summary>
        [ObservableProperty]
        public decimal _Altitude;
        /// <summary>
        /// 向上按钮是否触发
        /// </summary>
        [ObservableProperty]
        public bool _IsUpButtonOn = false;
        /// <summary>
        /// 向下按钮是否触发
        /// </summary>
        [ObservableProperty]
        public bool _IsDownButtonOn = false;
        /// <summary>
        /// 基层（是否是地面基础层）
        /// </summary>
        [ObservableProperty]
        public bool _IsBaseFloor = false;
        /// <summary>
        /// 楼层类型
        /// </summary>
        [ObservableProperty]
        public FloorLevel _IsTopOrBottom = FloorLevel.Middle;
        /// <summary>
        /// 无按钮，该楼层无按钮。有些大型商场镂空的楼层，只可以走滚梯。为此。
        /// </summary>
        [ObservableProperty]
        public bool _IsNoButton = false;

        #region 内部运算

        /// <summary>
        /// 设置按钮触发
        /// </summary>
        /// <param name="floorNumber"></param>
        /// <param name="up_or_down"></param>
        /// <returns>有对应楼层为true，非本楼层false</returns>
        public bool Set_IsUpButtonOn(int floorNumber, string up_or_down)
        {
            bool result = false;
            if (floorNumber == _FloorNumber)
            {
                if (up_or_down == "Up")
                {
                    IsUpButtonOn = true;
                }
                else if (up_or_down == "Down")
                {
                    IsDownButtonOn = true;
                }
                result = true;
            }

            return result;
        }

        
        #endregion

    }

    public enum FloorLevel
    {
        Top,
        Middle,
        Bottom
    }
}
